﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using BasePlatformNet;
using System.Threading;
using System.IO;
using BasePlatformCommon;

namespace L9SubSet
{
	public partial class Form_PlatformTool : Form
	{
		private string versionStr = "网口调试工具 v0.41 @ 2017.7.6";

		private BaseCoreNet baseCoreNet = null;

		private bool exitFlag = false;

		private int config_waitPacket_ms = 500;		// 在线检测 - 回包等待时间
		
		private int config_maxSubCtrlNum = 255;		// 在线检测 - 最大检测的分控数量 1-255
		private int config_maxEquipmentNum = 63;	// 在线检测 - 最大检测的附属设备数量 1-63

		private int config_getResult_ms = 800;		// 在线检测 - 获取结果周期

		private bool onlineTestRunning = false;

		private byte[] memData_read = new byte[256];
		private byte[] memData_write = new byte[256];
		private byte[] memData_batWrite = null;

		private byte[] memData_batRead = null;

		private string datFilePath = "";
		private string batReadBinFilePath = "";

		private bool batReadProcessing = false;
		private bool forceStopBatRead = false;
		private uint startAddr_batRead = 0;
		private uint readLength_batRead = 0;

		private bool batWriteProcessing = false;
		private bool forceStopBatWrite = false;
		private uint startAddr_batWrite = 0;

		private int initActiveDeviceIndex = 0;

		private string lastPath_DataFile = "";
		private string lastPath_BatDataFile = "";

		#region 委托定义与声明

		public delegate void PrintOnlineDetectResultDelegate(string str);
		public PrintOnlineDetectResultDelegate printOnlineDetectResultDelegate;
		public delegate void PrintReadResultDelegate(string str);
		public PrintReadResultDelegate printReadResultDelegate;
		public delegate void PrintBatReadResultDelegate(string str);
		public PrintBatReadResultDelegate printBatReadResultDelegate;
		public delegate void PrintBatReadLogDelegate(string str);
		public PrintBatReadLogDelegate printBatReadLogDelegate;
		public delegate void PrintBatWriteLogDelegate(string str);
		public PrintBatWriteLogDelegate printBatWriteLogDelegate;
		public delegate void BatReadDoneDelegate();
		public BatReadDoneDelegate batReadDoneDelegate;
		public delegate void BatWriteDoneDelegate();
		public BatWriteDoneDelegate batWriteDoneDelegate;
		public delegate void UpdateBatReadProcessValueDelegate(int value);
		public UpdateBatReadProcessValueDelegate updateBatReadProcessValueDelegate;
		public delegate void UpdateBatWriteProcessValueDelegate(int value);
		public UpdateBatWriteProcessValueDelegate updateBatWriteProcessValueDelegate;
		public delegate void EnableComponentsAfterBatReadDelegate();
		public EnableComponentsAfterBatReadDelegate enableComponentsAfterBatReadDelegate;
		public delegate void EnableComponentsAfterBatWriteDelegate();
		public EnableComponentsAfterBatWriteDelegate enableComponentsAfterBatWriteDelegate;
		
		#endregion

		private string section = "PlatTool";			// 多语言文件配置节名称

		private string tip = "提示";						// MessageBox 题头

		/*****************************************************************************************/

		// 构造函数
		public Form_PlatformTool(BaseCoreNet baseCoreNetExt, int activeDeviceIndex)
		{
			InitializeComponent();

			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
			this.Font = new System.Drawing.Font(this.Font.Name, 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel, ((byte)(134)));

			initUIConfigData();

			initDelegates();

			initEnvironment(baseCoreNetExt, activeDeviceIndex);

			refreshDeviceList();
		}

		// 初始化界面参数值
		private void initUIConfigData()
		{
			this.Text = versionStr;

			this.waitTimeTextBox.Text = config_waitPacket_ms.ToString();

			this.getResultSpanTextBox.Text = config_getResult_ms.ToString();

			this.maxSubNumTextBox.Text = config_maxSubCtrlNum.ToString();

			this.maxEquNumTextBox.Text = config_maxEquipmentNum.ToString();

			string all = "全局";
			if (LanguageOper.available == true)
			{
				all = LanguageOper.ReadValue(section, "str.0");
			}

			indexComboBox_read.Items.Clear();
			indexComboBox_write.Items.Clear();
			indexComboBox_write.Items.Add(all);
			indexComboBox_batWrite.Items.Clear();
			indexComboBox_batWrite.Items.Add(all);
			for(int k = 1; k <= 255; k++)
			{
				indexComboBox_read.Items.Add(k);
				indexComboBox_write.Items.Add(k);
				indexComboBox_batWrite.Items.Add(k);
				indexComboBox_batRead.Items.Add(k);
			}
			indexComboBox_read.SelectedIndex = 0;
			indexComboBox_write.SelectedIndex = 1;
			indexComboBox_batWrite.SelectedIndex = 1;
			indexComboBox_batRead.SelectedIndex = 0;

			commonValueComboBox.SelectedIndex = 0;
		}

		// 委托实例化
		private void initDelegates()
		{
			printOnlineDetectResultDelegate = new PrintOnlineDetectResultDelegate(printOnlineDetectResult);

			printReadResultDelegate = new PrintReadResultDelegate(printReadResult);
			printBatReadResultDelegate = new PrintBatReadResultDelegate(printBatReadResult);

			printBatReadLogDelegate = new PrintBatReadLogDelegate(printBatReadLog);
			printBatWriteLogDelegate = new PrintBatWriteLogDelegate(printBatWriteLog);

			updateBatReadProcessValueDelegate = new UpdateBatReadProcessValueDelegate(updateBatReadProcessValue);
			batReadDoneDelegate = new BatReadDoneDelegate(batReadDone);
			enableComponentsAfterBatReadDelegate = new EnableComponentsAfterBatReadDelegate(enableComponentsAfterBatRead);

			updateBatWriteProcessValueDelegate = new UpdateBatWriteProcessValueDelegate(updateBatWriteProcessValue);
			batWriteDoneDelegate = new BatWriteDoneDelegate(batWriteDone);
			enableComponentsAfterBatWriteDelegate = new EnableComponentsAfterBatWriteDelegate(enableComponentsAfterBatWrite);
		}

		// 初始化运行环境
		private void initEnvironment(BaseCoreNet baseCoreNetExt, int activeDeviceIndex)
		{
			// 初始化时的活跃网卡
			initActiveDeviceIndex = activeDeviceIndex;

			// 单例模式
			baseCoreNet = baseCoreNetExt;

			// 设置本地化语言
			if (LanguageOper.available == true)
			{
				setLanguageText();
			}
		}
	
		// 设置本地化语言
		public void setLanguageText()
		{
			if (LanguageOper.available == false)
			{
				return;
			}

			LanguageOper.SetCurrentCulture();

			tip = LanguageOper.ReadValue("Common", "tipStr");

			// 界面控件文字
			this.Text = LanguageOper.ReadValue(section, "platTool.Text");
			networkCardLabel.Text = LanguageOper.ReadValue(section, "networkCardLabel.Text");
			refreshButton.Text = LanguageOper.ReadValue(section, "refreshButton.Text");
			tabControl1.TabPages[0].Text = LanguageOper.ReadValue(section, "tabPages.0.Text");
			tabControl1.TabPages[1].Text = LanguageOper.ReadValue(section, "tabPages.1.Text");
			tabControl1.TabPages[2].Text = LanguageOper.ReadValue(section, "tabPages.2.Text");
			readGroupBox.Text = LanguageOper.ReadValue(section, "readGroupBox.Text");
			writeGroupBox.Text = LanguageOper.ReadValue(section, "writeGroupBox.Text");
			targetRLabel.Text = LanguageOper.ReadValue(section, "targetRLabel.Text");
			targetWLabel.Text = LanguageOper.ReadValue(section, "targetWLabel.Text");
			subRadioButton_read.Text = LanguageOper.ReadValue(section, "str.5");
			subRadioButton_write.Text = LanguageOper.ReadValue(section, "str.5");
			equRadioButton_read.Text = LanguageOper.ReadValue(section, "str.6");
			equRadioButton_write.Text = LanguageOper.ReadValue(section, "str.6");
			depthLabel_read.Text = LanguageOper.ReadValue(section, "str.7");
			depthLabel_write.Text = LanguageOper.ReadValue(section, "str.7");
			addrLabel_read.Text = LanguageOper.ReadValue(section, "addrLabel_read.Text");
			addrLabel_write.Text = LanguageOper.ReadValue(section, "addrLabel_write.Text");
			readButton.Text = LanguageOper.ReadValue(section, "readButton.Text");
			clearReadResultButton.Text = LanguageOper.ReadValue(section, "clearReadResultButton.Text");
			save2FileButton.Text = LanguageOper.ReadValue(section, "save2FileButton.Text");
			writeButton.Text = LanguageOper.ReadValue(section, "writeButton.Text");
			clearWritePreviewButton.Text = LanguageOper.ReadValue(section, "clearWritePreviewButton.Text");
			srcLabel.Text = LanguageOper.ReadValue(section, "srcLabel.Text");
			manualDataRadioButton.Text = LanguageOper.ReadValue(section, "manualDataRadioButton.Text");
			fileDataRadioButton.Text = LanguageOper.ReadValue(section, "fileDataRadioButton.Text");
			selectDataFileButton.Text = LanguageOper.ReadValue(section, "selectDataFileButton.Text");
			commonValueComboBox.Items[0] = LanguageOper.ReadValue(section, "str.8");
			batchReadGroupBox.Text = LanguageOper.ReadValue(section, "batchReadGroupBox.Text");
			batchWriteGroupBox.Text = LanguageOper.ReadValue(section, "batchWriteGroupBox.Text");
			brTargetLabel.Text = LanguageOper.ReadValue(section, "targetRLabel.Text");
			bwTargetLabel.Text = LanguageOper.ReadValue(section, "targetWLabel.Text");
			subRadioButton_batRead.Text = LanguageOper.ReadValue(section, "str.5");
			subRadioButton_batWrite.Text = LanguageOper.ReadValue(section, "str.5");
			equRadioButton_batRead.Text = LanguageOper.ReadValue(section, "str.6");
			equRadioButton_batWrite.Text = LanguageOper.ReadValue(section, "str.6");
			brDepthLabel.Text = LanguageOper.ReadValue(section, "str.7");
			bwDepthLabel.Text = LanguageOper.ReadValue(section, "str.7");
			brStartAddrLabel.Text = LanguageOper.ReadValue(section, "brStartAddrLabel.Text");
			bwStartAddrLabel.Text = LanguageOper.ReadValue(section, "bwStartAddrLabel.Text");
			brLengthLabel.Text = LanguageOper.ReadValue(section, "brLengthLabel.Text");
			bwLengthLabel.Text = LanguageOper.ReadValue(section, "bwLengthLabel.Text");
			batReadButton.Text = LanguageOper.ReadValue(section, "batReadButton.Text");
			batWriteButton.Text = LanguageOper.ReadValue(section, "batWriteButton.Text");
			brAddrTypeLabel.Text = LanguageOper.ReadValue(section, "str.9");
			bwAddrTypeLabel.Text = LanguageOper.ReadValue(section, "str.9");
			brSaveLabel.Text = LanguageOper.ReadValue(section, "brSaveLabel.Text");
			selectDataFileButton_batRead.Text = LanguageOper.ReadValue(section, "selectDataFileButton_batRead.Text");
			clearResultButton_batRead.Text = LanguageOper.ReadValue(section, "clearResultButton_batRead.Text");
			clearWritePreviewButton_batWrite.Text = LanguageOper.ReadValue(section, "clearWritePreviewButton_batWrite.Text");
			brLogGroupBox.Text = LanguageOper.ReadValue(section, "str.10");
			bwLogGroupBox.Text = LanguageOper.ReadValue(section, "str.10");
			bwSrcLabel.Text = LanguageOper.ReadValue(section, "bwSrcLabel.Text");
			manualBatDataRadioButton.Text = LanguageOper.ReadValue(section, "manualBatDataRadioButton.Text");
			fileBatDataRadioButton.Text = LanguageOper.ReadValue(section, "fileBatDataRadioButton.Text");
			selectDataFileButton_batWrite.Text = LanguageOper.ReadValue(section, "selectDataFileButton_batWrite.Text");
			brProcessLabel.Text = LanguageOper.ReadValue(section, "brProcessLabel.Text");
			bwProcessLabel.Text = LanguageOper.ReadValue(section, "bwProcessLabel.Text");
			saveLogButton_batRead.Text = LanguageOper.ReadValue(section, "str.11");
			saveLogButton_batWrite.Text = LanguageOper.ReadValue(section, "str.11");
			clearLogButton_batRead.Text = LanguageOper.ReadValue(section, "str.12");
			clearLogButton_batWrite.Text = LanguageOper.ReadValue(section, "str.12");
			if (LanguageOper.LocalLanguage != LanguageEnum.EN)
			{
				networkCardLabel.Location = new Point(12, 19);
				targetRLabel.Location = new Point(6, 26);
				targetWLabel.Location = new Point(6, 26);
				fileDataRadioButton.Location = new Point(124, 8);
				depthLabel_read.Location = new Point(210, 26);
				depthLabel_write.Location = new Point(210, 26);
				brTargetLabel.Location = new Point(6, 26);
				bwTargetLabel.Location = new Point(6, 26);
				brDepthLabel.Location = new Point(210, 26);
				bwDepthLabel.Location = new Point(210, 26);
				brLengthLabel.Location = new Point(500, 26);
				bwLengthLabel.Location = new Point(500, 26);
				fileBatDataRadioButton.Location = new Point(124, 8);
			}
			else
			{
				networkCardLabel.Location = new Point(20, 19);
				targetRLabel.Location = new Point(18, 26);
				targetWLabel.Location = new Point(18, 26);
				fileDataRadioButton.Location = new Point(135, 8);
				depthLabel_read.Location = new Point(230, 26);
				depthLabel_write.Location = new Point(230, 26);
				brTargetLabel.Location = new Point(18, 26);
				bwTargetLabel.Location = new Point(18, 26);
				brDepthLabel.Location = new Point(230, 26);
				bwDepthLabel.Location = new Point(230, 26);
				brLengthLabel.Location = new Point(510, 26);
				bwLengthLabel.Location = new Point(510, 26);
				fileBatDataRadioButton.Location = new Point(133, 8);
			}
		}

		// 刷新网卡列表
		private void refreshDeviceList()
		{
			if (baseCoreNet != null)
			{
				// 查询网口列表信息
				List<NetDeviceInfo> devList = baseCoreNet.getNetDeviceInfoList();

				deviceComboBox.Items.Clear();
				int selectIndex = -1;
				int index = -1;

				string activeStr = "【活跃】";
				if (LanguageOper.available == true)
				{
					activeStr = LanguageOper.ReadValue(section, "str.1");
				}
				
				foreach (NetDeviceInfo devInfo in devList)
				{
					index++;
					
					if(index == initActiveDeviceIndex)
					{
						deviceComboBox.Items.Add(activeStr + devInfo.name);
						selectIndex = index;
						initActiveDeviceIndex = -1;
						continue;
					}
					
					if (devInfo.activeStatus == true)
					{
						deviceComboBox.Items.Add(activeStr + devInfo.name);
						selectIndex = index;
					}
					else
					{
						deviceComboBox.Items.Add(devInfo.name);
					}
				}

				if (deviceComboBox.Items.Count > 0)
				{
					if (selectIndex == -1)
					{
						deviceComboBox.SelectedIndex = 0;
					}
					else
					{
						deviceComboBox.SelectedIndex = selectIndex;
					}
				}
			}
		}

		#region 在线检测

		// 在线检测结果提取主过程 - 线程方法
		private void onlineTestProcess()
		{
			int num = -1;
			while (true)
			{
				if (exitFlag == true)
				{
					break;
				}
				else if (onlineTestRunning == false)
				{
					Thread.Sleep(500);
					continue;
				}

				num++;

				// 获取在线检测结果 - 网口连接设备的拓扑结构链
				string topologyChain = baseCoreNet.getDeviceTopologyChain();
				topologyChain = "loop = " + num + ", " + topologyChain;

				// 打印检测结果
				if (exitFlag == false && onlineTestRunning == true)
				{
					this.detectResultTextBox.BeginInvoke(printOnlineDetectResultDelegate, topologyChain);
				}

				Thread.Sleep(config_getResult_ms);
			}
		}

		#endregion

		#region 读写分控

		// 读 分控 操作
		private void readSubProcess()
		{
			try
			{
				int devIndex = deviceComboBox.SelectedIndex;
				int subIndex = indexComboBox_read.SelectedIndex + 1;
				uint memAddr = 0x0;

				try
				{
					if (addrTextBox_read.Text.Trim().ToLower().StartsWith("0x"))
					{
						memAddr = Convert.ToUInt32(addrTextBox_read.Text.Trim().ToLower(), 16);
					}
					else
					{
						memAddr = Convert.ToUInt32(addrTextBox_read.Text.Trim().ToLower(), 10);
					}
				}
				catch (Exception)
				{
					string msg = "读址解析错误";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.0");
					}
					
					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
					
					return;
				}

				byte[] memData = new byte[256];
				bool timeout = baseCoreNet.readSubMem(devIndex, subIndex, memAddr, ref memData);

				if (timeout == true)
				{
					string msg = "读操作超时";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.1");
					}
					this.BeginInvoke(printReadResultDelegate, msg);
				}
				else
				{
					this.BeginInvoke(printReadResultDelegate, Tools.Byte2HexStringFriendly(memData));
					Array.Copy(memData, memData_read, 256);
					save2FileButton.Enabled = true;
				}
			}
			catch (Exception ex)
			{
				string msg = "读分控操作错误：";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.2");
				}
				MessageBoxEx.Show(this, msg + ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		// 读 附属设备 操作
		private void readEquProcess()
		{
			try
			{
				int devIndex = deviceComboBox.SelectedIndex;
				int equIndex = indexComboBox_read.SelectedIndex + 1;
				uint memAddr = 0x0;

				try
				{
					if (addrTextBox_read.Text.Trim().ToLower().StartsWith("0x"))
					{
						memAddr = Convert.ToUInt32(addrTextBox_read.Text.Trim().ToLower(), 16);
					}
					else
					{
						memAddr = Convert.ToUInt32(addrTextBox_read.Text.Trim().ToLower(), 10);
					}
				}
				catch (Exception)
				{
					string msg = "读址解析错误";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.0");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);

					return;
				}

				byte[] memData = new byte[256];
				bool timeout = baseCoreNet.readEquMem(devIndex, equIndex, memAddr, ref memData);

				if (timeout == true)
				{
					string msg = "读操作超时";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.1");
					}
					this.BeginInvoke(printReadResultDelegate, msg);
				}
				else
				{
					this.BeginInvoke(printReadResultDelegate, Tools.Byte2HexStringFriendly(memData));
					Array.Copy(memData, memData_read, 256);
					save2FileButton.Enabled = true;
				}
			}
			catch (Exception ex)
			{
				string msg = "读附属设备操作错误：";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.3");
				}

				MessageBoxEx.Show(this, msg + ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		// 写 分控 操作
		private void writeSubProcess()
		{
			try
			{
				int devIndex = deviceComboBox.SelectedIndex;
				int subIndex = indexComboBox_write.SelectedIndex;	// 因有全局写操作选项，注意区别读操作的 +1 问题
				uint memAddr = 0x0;

				try
				{
					if (addrTextBox_write.Text.Trim().ToLower().StartsWith("0x"))
					{
						memAddr = Convert.ToUInt32(addrTextBox_write.Text.Trim().ToLower(), 16);
					}
					else
					{
						memAddr = Convert.ToUInt32(addrTextBox_write.Text.Trim().ToLower(), 10);
					}
				}
				catch (Exception)
				{
					string msg = "写地址解析错误";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.4");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
					
					return;
				}

				// 全局写操作
				if (indexComboBox_write.SelectedIndex == 0)
				{
					baseCoreNet.writeSubMem(devIndex, subIndex, memAddr, memData_write, true);
				}
				// 定点写操作
				else
				{
					baseCoreNet.writeSubMem(devIndex, subIndex, memAddr, memData_write, false);
				}

				string msg1 = "分控写入成功";
				if (LanguageOper.available == true)
				{
					msg1 = LanguageOper.ReadValue(section, "msgStr.5");
				}

				MessageBoxEx.Show(this, msg1, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);

				return;
			}
			catch (Exception ex)
			{
				string msg = "写分控操作错误：";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.6");
				}

				MessageBoxEx.Show(this, msg + ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		// 写 附属设备 操作
		private void writeEquProcess()
		{
			try
			{
				int devIndex = deviceComboBox.SelectedIndex;
				int equIndex = indexComboBox_write.SelectedIndex;	// 因有全局写操作选项，注意区别读操作的 +1 问题
				uint memAddr = 0x0;

				try
				{
					if (addrTextBox_write.Text.Trim().ToLower().StartsWith("0x"))
					{
						memAddr = Convert.ToUInt32(addrTextBox_write.Text.Trim().ToLower(), 16);
					}
					else
					{
						memAddr = Convert.ToUInt32(addrTextBox_write.Text.Trim().ToLower(), 10);
					}
				}
				catch (Exception)
				{
					string msg = "写地址解析错误";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.4");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);

					return;
				}

				// 全局写操作
				if (indexComboBox_write.SelectedIndex == 0)
				{
					baseCoreNet.writeEquMem(devIndex, equIndex, memAddr, memData_write, true);
				}
				// 定点写操作
				else
				{
					baseCoreNet.writeEquMem(devIndex, equIndex, memAddr, memData_write, false);
				}

				string msg1 = "附属设备写入成功";
				if (LanguageOper.available == true)
				{
					msg1 = LanguageOper.ReadValue(section, "msgStr.7");
				}

				MessageBoxEx.Show(this, msg1, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);

				return;
			}
			catch (Exception ex)
			{
				string msg = "写附属设备操作错误：";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.8");
				}

				MessageBoxEx.Show(this, msg + ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		// 批量读 分控/附属设备 操作入口
		private void batReadEntry()
		{
			try
			{
				int devIndex = deviceComboBox.SelectedIndex;
				int subIndex = indexComboBox_batRead.SelectedIndex + 1;
				uint memAddr = 0x0;

				try
				{
					if (addrTextBox_batRead.Text.Trim().ToLower().StartsWith("0x"))
					{
						memAddr = Convert.ToUInt32(addrTextBox_batRead.Text.Trim().ToLower(), 16);
					}
					else
					{
						memAddr = Convert.ToUInt32(addrTextBox_batRead.Text.Trim().ToLower(), 10);
					}

					startAddr_batRead = memAddr;

					// 识别地址类型
					string addrType = "";

					string addrTypeVal_0 = "Flash保护区";
					string addrTypeVal_1 = "Flash地址";
					string addrTypeVal_2 = "普通地址";
					if (LanguageOper.available == true)
					{
						addrTypeVal_0 = LanguageOper.ReadValue(section, "str.2");
						addrTypeVal_1 = LanguageOper.ReadValue(section, "str.3");
						addrTypeVal_2 = LanguageOper.ReadValue(section, "str.4");
					}

					// 批量读 分控 操作
					if (subRadioButton_batRead.Checked)
					{
						if (memAddr >= 0xC00000 && memAddr <= 0xC3FFFF)
						{
							addrType = addrTypeVal_0;
						}
						else if (memAddr >= 0x440000 && memAddr <= 0x47FFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0xC80000 && memAddr <= 0xCBFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x4cC0000 && memAddr <= 0x4FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x600000 && memAddr <= 0x6FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else
						{
							addrType = addrTypeVal_2;
						}
						startAddrType_batRead.Text = addrType;

						// 解析读取长度
						if (totalLengthTextBox_batRead.Text.Trim().ToLower().StartsWith("0x"))
						{
							readLength_batRead = Convert.ToUInt32(totalLengthTextBox_batRead.Text.Trim(), 16);
						}
						else
						{
							readLength_batRead = Convert.ToUInt32(totalLengthTextBox_batRead.Text.Trim(), 10);
						}

						string msg = string.Format("批量读取分控：级联深度 = {0}, 起始地址 = {1}, 地址类型 = {2}, 读取长度 = {3} Bytes",	subIndex, addrTextBox_batRead.Text, addrType, readLength_batRead);
						if (LanguageOper.available == true)
						{
							msg = string.Format(LanguageOper.ReadValue(section, "msgStr.9"), subIndex, addrTextBox_batRead.Text, addrType, readLength_batRead);
						}
					
						this.BeginInvoke(printBatReadLogDelegate, msg);
					}
					// 批量读 附属设备 操作
					else
					{
						if (memAddr >= 0xE00000 && memAddr <= 0xE3FFFF)
						{
							addrType = addrTypeVal_0;
						}
						else if (memAddr >= 0x440000 && memAddr <= 0x47FFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0xE80000 && memAddr <= 0xEBFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x4c0000 && memAddr <= 0x4FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x600000 && memAddr <= 0x6FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else
						{
							addrType = addrTypeVal_2;
						}
						startAddrType_batRead.Text = addrType;

						// 解析读取长度
						if (totalLengthTextBox_batRead.Text.Trim().ToLower().StartsWith("0x"))
						{
							readLength_batRead = Convert.ToUInt32(totalLengthTextBox_batRead.Text.Trim(), 16);
						}
						else
						{
							readLength_batRead = Convert.ToUInt32(totalLengthTextBox_batRead.Text.Trim(), 10);
						}

						string msg = string.Format("批量读取附属设备：级联深度 = {0}, 起始地址 = {1}, 地址类型 = {2}, 读取长度 = {3} Bytes", subIndex, addrTextBox_batRead.Text, addrType, readLength_batRead);
						if (LanguageOper.available == true)
						{
							msg = string.Format(LanguageOper.ReadValue(section, "msgStr.10"), subIndex, addrTextBox_batRead.Text, addrType, readLength_batRead);
						}

						this.BeginInvoke(printBatReadLogDelegate, msg);
					}
				}
				catch (Exception)
				{
					string msg = "起始读地址 或 读取长度 解析错误";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.11");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
					
					return;
				}

				if (readLength_batRead <= 0)
				{
					string msg = "读取长度应为正值";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.12");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
					
					return;
				}

				if (batReadProcessing == true)
				{
					string msg = "正在执行其他的批量读操作, 请稍后重试";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.13");
					}
					
					this.BeginInvoke(printBatReadLogDelegate, msg);
					
					return;
				}

				// 清除旧数据
				clearResultButton_batRead_Click(null, null);

				// 禁用界面控件
				disableComponentsBeforeBatRead();
				logRichTextBox_batRead.Text = "";

				string text = "强制停止";
				if (LanguageOper.available == true)
				{
					text = LanguageOper.ReadValue(section, "batReadButton.Text.1");
				}

				// 批量读 分控 操作
				if (subRadioButton_batRead.Checked)
				{
					Thread t = new Thread(() => 
					{
						batReadSubProcess(devIndex, subIndex);
					});
					t.IsBackground = true;
					t.Start();
					batReadButton.Text = text;
				}
				// 批量读 附属设备 操作
				else
				{
					Thread t = new Thread(() => 
					{
						batReadEquProcess(devIndex, subIndex);
					});
					t.IsBackground = true;
					t.Start();
					batReadButton.Text = text;
				}
				
				return;
			}
			catch (Exception ex)
			{
				string msg = "批量读分控操作错误：";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.14");
				}

				MessageBoxEx.Show(this, msg + ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		// 批量写 分控/附属设备 操作入口
		private void batWriteEntry()
		{
			try
			{
				int devIndex = deviceComboBox.SelectedIndex;
				int subIndex = indexComboBox_batWrite.SelectedIndex;	// 因有全局写操作选项，注意区别读操作的 +1 问题
				uint memAddr = 0x0;
				try
				{
					if (addrTextBox_batWrite.Text.Trim().ToLower().StartsWith("0x"))
					{
						memAddr = Convert.ToUInt32(addrTextBox_batWrite.Text.Trim().ToLower(), 16);
					}
					else
					{
						memAddr = Convert.ToUInt32(addrTextBox_batWrite.Text.Trim().ToLower(), 10);
					}

					startAddr_batWrite = memAddr;

					// 识别地址类型
					string addrType = "";

					string addrTypeVal_0 = "Flash保护区";
					string addrTypeVal_1 = "Flash地址";
					string addrTypeVal_2 = "普通地址";
					if (LanguageOper.available == true)
					{
						addrTypeVal_0 = LanguageOper.ReadValue(section, "str.2");
						addrTypeVal_1 = LanguageOper.ReadValue(section, "str.3");
						addrTypeVal_2 = LanguageOper.ReadValue(section, "str.4");
					}

					// 批量写 分控 操作
					if (subRadioButton_batWrite.Checked)
					{
						if (memAddr >= 0xC00000 && memAddr <= 0xC3FFFF)
						{
							addrType = addrTypeVal_0;
						}
						else if (memAddr >= 0x440000 && memAddr <= 0x47FFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0xC80000 && memAddr <= 0xCBFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x4c0000 && memAddr <= 0x4FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x600000 && memAddr <= 0x6FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else
						{
							addrType = addrTypeVal_2;
						}
						startAddrType_batWrite.Text = addrType;

						string msg = string.Format("批量写入分控： 起始地址 = {0}, 地址类型 = {1}, 数据长度 = {2} Bytes", addrTextBox_batWrite.Text, addrType, memData_batWrite.Length);
						if (LanguageOper.available == true)
						{
							msg = string.Format(LanguageOper.ReadValue(section, "msgStr.15"), addrTextBox_batWrite.Text, addrType, memData_batWrite.Length);
						}
						
						this.BeginInvoke(printBatWriteLogDelegate, msg);
					}
					// 批量写 附属设备 操作
					else
					{
						if (memAddr >= 0xE00000 && memAddr <= 0xE3FFFF)
						{
							addrType = addrTypeVal_0;
						}
						else if (memAddr >= 0x440000 && memAddr <= 0x47FFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0xE80000 && memAddr <= 0xEBFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x4c0000 && memAddr <= 0x4FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else if (memAddr >= 0x600000 && memAddr <= 0x6FFFFF)
						{
							addrType = addrTypeVal_1;
						}
						else
						{
							addrType = addrTypeVal_2;
						}
						startAddrType_batWrite.Text = addrType;

						string msg = string.Format("批量写入附属设备： 起始地址 = {0}, 地址类型 = {1}, 数据长度 = {2} Bytes", addrTextBox_batWrite.Text, addrType, memData_batWrite.Length);
						if (LanguageOper.available == true)
						{
							msg = string.Format(LanguageOper.ReadValue(section, "msgStr.15"), addrTextBox_batWrite.Text, addrType, memData_batWrite.Length);
						}

						this.BeginInvoke(printBatWriteLogDelegate, msg);
					}
				}
				catch (Exception)
				{
					string msg = "起始写地址解析错误";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.16");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
					
					return;
				}

				if (batWriteProcessing == true)
				{
					string msg = "正在执行其他的批量写操作, 请稍后重试";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.17");
					}

					this.BeginInvoke(printBatWriteLogDelegate, msg);
					
					return;
				}

				// 禁用界面控件
				disableComponentsBeforeBatWrite();
				logRichTextBox_batWrite.Text = "";

				string text = "强制停止";
				if (LanguageOper.available == true)
				{
					text = LanguageOper.ReadValue(section, "batWriteButton.Text.1");
				}

				// 批量写 分控 操作
				if (subRadioButton_batWrite.Checked)
				{
					Thread t = new Thread(() => 
					{
						batWriteSubProcess(devIndex, subIndex);
					});
					t.IsBackground = true;
					t.Start();
					batWriteButton.Text = text;
				}
				// 批量写 附属设备 操作
				else
				{
					Thread t = new Thread(() => 
					{
						batWriteEquProcess(devIndex, subIndex);
					});
					t.IsBackground = true;
					t.Start();
					batWriteButton.Text = text;
				}
				return;
			}
			catch (Exception ex)
			{
				string msg = "批量写分控操作错误：";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.18");
				}

				MessageBoxEx.Show(this, msg + ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		// 批量读 分控 线程方法
		private void batReadSubProcess(int devIndex, int subIndex)
		{
			bool withProcess = true;

			bool readTimeout = false;

			batReadProcessing = true;

			int readProcessValue = 0;
			this.BeginInvoke(updateBatReadProcessValueDelegate, readProcessValue);

			int length = (int)readLength_batRead;

			startAddr_batRead = startAddr_batRead / 256 * 256;		// 起始读取地址, 按照 256 bytes 取整 
			int totalReadStep = length / 256;
			if (length % 256 > 0)									// 处理末尾数据
			{
				totalReadStep++;
				length = totalReadStep * 256;
			}

			byte[] readData_tmp = new byte[256];
			byte[] readData = new byte[length];

			/*********************************** 读取数据 *****************************************/

			for (int readStep = 0; readStep < totalReadStep; readStep++)
			{
				if (forceStopBatRead)
				{
					forceStopBatRead = false;
					break;
				}

				uint currentReadAddr = (uint)(startAddr_batRead + readStep * 256);
				this.BeginInvoke(printBatReadLogDelegate, "currentReadAddr = 0x" + currentReadAddr.ToString("X2"));

				bool timeout = true;

				for (int k = 0; k < 3; k++)
				{
					timeout = baseCoreNet.readSubMem(devIndex, subIndex, currentReadAddr, ref readData_tmp);
					if (timeout == false)
					{
						break;
					}
					else
					{
						this.BeginInvoke(printBatReadLogDelegate, "read timeout, retry " + (k + 1) + " times");
						continue;
					}
				}

				if (timeout == true)
				{
					this.BeginInvoke(printBatReadLogDelegate, "Read Error: timeout");
					readTimeout = true;
					break;
				}
				else
				{
					Array.Copy(readData_tmp, 0, readData, readStep * 256, 256);
				}

				readProcessValue = readStep * 100 / totalReadStep;
				if (readProcessValue > 100)
				{
					readProcessValue = 100;
				} 
				this.BeginInvoke(updateBatReadProcessValueDelegate, readProcessValue);
			}

			/********************************* End 读取数据 ***************************************/

			if (withProcess)
			{
				readProcessValue = 100;
				this.BeginInvoke(updateBatReadProcessValueDelegate, readProcessValue);
			}

			if (readTimeout == false)
			{
				memData_batRead = new byte[readData.Length];
				Array.Copy(readData, memData_batRead, readData.Length);
				this.BeginInvoke(printBatReadResultDelegate, Tools.Byte2HexString4RBF(readData));
			}
			else
			{
				memData_batRead = null;
			}

			batReadProcessing = false;
			this.BeginInvoke(printBatReadLogDelegate, "Batch ReadSubMem Done");
			this.BeginInvoke(batReadDoneDelegate);
		}

		// 批量读 附属设备 线程方法
		private void batReadEquProcess(int devIndex, int subIndex)
		{
			bool withProcess = true;

			bool readTimeout = false;

			batReadProcessing = true;

			int readProcessValue = 0;
			this.BeginInvoke(updateBatReadProcessValueDelegate, readProcessValue);

			int length = (int)readLength_batRead;

			startAddr_batRead = startAddr_batRead / 256 * 256;		// 起始读取地址, 按照 256 bytes 取整 
			int totalReadStep = length / 256;
			if (length % 256 > 0)									// 处理末尾数据
			{
				totalReadStep++;
				length = totalReadStep * 256;
			}

			byte[] readData_tmp = new byte[256];
			byte[] readData = new byte[length];

			/*********************************** 读取数据 *****************************************/

			for (int readStep = 0; readStep < totalReadStep; readStep++)
			{
				if (forceStopBatRead)
				{
					forceStopBatRead = false;
					break;
				}

				uint currentReadAddr = (uint)(startAddr_batRead + readStep * 256);
				this.BeginInvoke(printBatReadLogDelegate, "currentReadAddr = 0x" + currentReadAddr.ToString("X2"));

				bool timeout = true;

				for (int k = 0; k < 3; k++)
				{
					timeout = baseCoreNet.readEquMem(devIndex, subIndex, currentReadAddr, ref readData_tmp);
					if (timeout == false)
					{
						break;
					}
					else
					{
						this.BeginInvoke(printBatReadLogDelegate, "read timeout, retry " + (k + 1) + " times");
						continue;
					}
				}

				if (timeout == true)
				{
					this.BeginInvoke(printBatReadLogDelegate, "Read Error: timeout");
					readTimeout = true;
					break;
				}
				else
				{
					Array.Copy(readData_tmp, 0, readData, readStep * 256, 256);
				}

				readProcessValue = readStep * 100 / totalReadStep;
				if (readProcessValue > 100)
				{
					readProcessValue = 100;
				} 
				this.BeginInvoke(updateBatReadProcessValueDelegate, readProcessValue);
			}

			/********************************* End 读取数据 ***************************************/

			if (withProcess)
			{
				readProcessValue = 100;
				this.BeginInvoke(updateBatReadProcessValueDelegate, readProcessValue);
			}

			if (readTimeout == false)
			{
				memData_batRead = new byte[readData.Length];
				Array.Copy(readData, memData_batRead, readData.Length);
				this.BeginInvoke(printBatReadResultDelegate, Tools.Byte2HexString4RBF(readData));
			}
			else
			{
				memData_batRead = null;
			}

			batReadProcessing = false;
			this.BeginInvoke(printBatReadLogDelegate, "Batch ReadEquMem Done");
			this.BeginInvoke(batReadDoneDelegate);
		}

		// 批量写 分控 线程方法
		private void batWriteSubProcess(int devIndex, int subIndex)
		{
			bool withProcess = true;

			batWriteProcessing = true;

			int updateProcessValue = 0;

			uint blockSize = 4 * 1024;		// block 大小：4KB
			int eraseTimeSpan = 400;		// 擦除时间间隔
			int updateTimeSpan = 10;		// 发写入包时间间隔
			bool withErase = false;			// 带有擦除操作

			int length = memData_batWrite.Length;

			int blockNum = (int)(length / blockSize);
			if (length % blockSize > 0)
			{
				blockNum++;
			}

			byte[] loadData_0 = new byte[256];
			byte[] loadData = new byte[256];
			for (int k = 0; k < 256; k++)
			{
				loadData_0[k] = 0x0;
				loadData[k] = 0x0;
			}

			// Flash地址, 需带有擦除操作
			if (startAddr_batWrite >= 0x440000 && startAddr_batWrite <= 0x47FFFF ||
				startAddr_batWrite >= 0xC80000 && startAddr_batWrite <= 0xCBFFFF ||
				startAddr_batWrite >= 0x4c0000 && startAddr_batWrite <= 0x4FFFFF ||
				startAddr_batWrite >= 0x600000 && startAddr_batWrite <= 0x6FFFFF)
			{
				withErase = true;
			}
			
			uint currentClearAddr = 0x0;						// 擦除地址
			uint currentRWAddr = (uint)startAddr_batWrite;		// 写入地址

			/*********************************** 写入数据 *****************************************/

			// 数据长度 length <= 256 Bytes
			if (length <= 256)
			{
				// 擦除 block
				if (withErase)
				{
					uint currentClearAddr_tmp = (currentRWAddr + 0x00100000) / blockSize * blockSize;
					if (currentClearAddr_tmp != currentClearAddr)
					{
						// 更新擦除地址
						currentClearAddr = currentClearAddr_tmp;

						// 发送擦除包
						baseCoreNet.writeSubMem(devIndex, subIndex, currentClearAddr, loadData_0, false);
						this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentClearAddr.ToString("X2") + " [Erase]");

						// 等待擦除时间间隔
						Thread.Sleep(eraseTimeSpan);
					}
				}

				// 发送数据包
				Array.Copy(memData_batWrite, loadData, length);
				baseCoreNet.writeSubMem(devIndex, subIndex, currentRWAddr, loadData, false);
				this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentRWAddr.ToString("X2"));
				
				// 等待写入时间间隔
				Thread.Sleep(updateTimeSpan);
			}
			// 数据长度 length > 256 Bytes
			else
			{
				int packetNum = length / 256;
				int clearGap = (int)(blockSize / 256);
				for (int i = 0; i < packetNum; i++)		// 耗时操作
				{
					if (forceStopBatWrite)
					{
						updateProcessValue = 0;
						forceStopBatWrite = false;
						batWriteProcessing = false;
						this.BeginInvoke(printBatWriteLogDelegate, "Batch WriteSubMem Force Stoped !");
						this.BeginInvoke(enableComponentsAfterBatWriteDelegate);
						return;
					}

					if (withErase)
					{
						uint currentClearAddr_tmp = (currentRWAddr + 0x00100000) / blockSize * blockSize;
						if (currentClearAddr_tmp != currentClearAddr)
						{
							// 更新擦除地址
							currentClearAddr = currentClearAddr_tmp;
							
							// 发送擦除包
							baseCoreNet.writeSubMem(devIndex, subIndex, currentClearAddr, loadData_0, false);
							this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentClearAddr.ToString("X2") + " [Erase]");
							
							// 等待擦除时间间隔
							Thread.Sleep(eraseTimeSpan);
						}
					}

					// 发送数据包
					Array.Copy(memData_batWrite, i * 256, loadData, 0, 256);
					baseCoreNet.writeSubMem(devIndex, subIndex, currentRWAddr, loadData, false);
					this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentRWAddr.ToString("X2"));
					currentRWAddr += 256;
					
					// 等待写入时间间隔
					Thread.Sleep(updateTimeSpan);

					if (withProcess)
					{
						updateProcessValue = i * 100 / packetNum;
						this.BeginInvoke(updateBatWriteProcessValueDelegate, updateProcessValue);
					}
				}

				if (length % 256 > 0)	// 末尾数据 - 目前数据已对齐, 无末尾数据
				{
					;
				}
			}

			/********************************* End 写入数据 ***************************************/

			if (withProcess)
			{
				updateProcessValue = 100;
				this.BeginInvoke(updateBatWriteProcessValueDelegate, updateProcessValue);
			}

			batWriteProcessing = false;
			this.BeginInvoke(printBatWriteLogDelegate, "Batch WriteSubMem Done");
			this.BeginInvoke(batWriteDoneDelegate);
		}

		// 批量写 附属设备 线程方法
		private void batWriteEquProcess(int devIndex, int subIndex)
		{
			bool withProcess = true;

			batWriteProcessing = true;

			int updateProcessValue = 0;

			uint blockSize = 4 * 1024;		// block 大小：4KB
			int eraseTimeSpan = 400;		// 擦除时间间隔
			int updateTimeSpan = 10;		// 发写入包时间间隔
			bool withErase = false;			// 带有擦除操作

			int length = memData_batWrite.Length;

			int blockNum = (int)(length / blockSize);
			if (length % blockSize > 0)
			{
				blockNum++;
			}

			byte[] loadData_0 = new byte[256];
			byte[] loadData = new byte[256];
			for (int k = 0; k < 256; k++)
			{
				loadData_0[k] = 0x0;
				loadData[k] = 0x0;
			}

			// Flash地址, 需带有擦除操作
			if (startAddr_batWrite >= 0x440000 && startAddr_batWrite <= 0x47FFFF ||
				startAddr_batWrite >= 0xE80000 && startAddr_batWrite <= 0xEBFFFF ||
				startAddr_batWrite >= 0x4c0000 && startAddr_batWrite <= 0x4FFFFF ||
				startAddr_batWrite >= 0x600000 && startAddr_batWrite <= 0x6FFFFF)
			{
				withErase = true;
			}

			uint currentClearAddr = 0x0;						// 擦除地址
			uint currentRWAddr = (uint)startAddr_batWrite;		// 写入地址

			/*********************************** 写入数据 *****************************************/

			// 数据长度 length <= 256 Bytes
			if (length <= 256)
			{
				// 擦除 block
				if (withErase)
				{
					uint currentClearAddr_tmp = (currentRWAddr + 0x00100000) / blockSize * blockSize;
					if (currentClearAddr_tmp != currentClearAddr)
					{
						// 更新擦除地址
						currentClearAddr = currentClearAddr_tmp;

						// 发送擦除包
						baseCoreNet.writeEquMem(devIndex, subIndex, currentClearAddr, loadData_0, false);
						this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentClearAddr.ToString("X2") + " [Erase]");

						// 等待擦除时间间隔
						Thread.Sleep(eraseTimeSpan);
					}
				}

				// 发送数据包
				Array.Copy(memData_batWrite, loadData, length);
				baseCoreNet.writeEquMem(devIndex, subIndex, currentRWAddr, loadData, false);
				this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentRWAddr.ToString("X2"));
				
				// 等待写入时间间隔
				Thread.Sleep(updateTimeSpan);
			}
			// 数据长度 length > 256 Bytes
			else
			{
				int packetNum = length / 256;
				int clearGap = (int)(blockSize / 256);
				for (int i = 0; i < packetNum; i++)		// 耗时操作
				{
					if (forceStopBatWrite)
					{
						updateProcessValue = 0;
						forceStopBatWrite = false;
						batWriteProcessing = false;
						this.BeginInvoke(printBatWriteLogDelegate, "Batch WriteSubMem Force Stoped !");
						this.BeginInvoke(enableComponentsAfterBatWriteDelegate);
						return;
					}

					if (withErase)
					{
						uint currentClearAddr_tmp = (currentRWAddr + 0x00100000) / blockSize * blockSize;
						if (currentClearAddr_tmp != currentClearAddr)
						{
							// 更新擦除地址
							currentClearAddr = currentClearAddr_tmp;

							// 发送擦除包
							baseCoreNet.writeEquMem(devIndex, subIndex, currentClearAddr, loadData_0, false);
							this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentClearAddr.ToString("X2") + " [Erase]");

							// 等待擦除时间间隔
							Thread.Sleep(eraseTimeSpan);
						}
					}

					// 发送数据包
					Array.Copy(memData_batWrite, i * 256, loadData, 0, 256);
					baseCoreNet.writeEquMem(devIndex, subIndex, currentRWAddr, loadData, false);
					this.BeginInvoke(printBatWriteLogDelegate, "writeSubMem: addr = " + currentRWAddr.ToString("X2"));
					currentRWAddr += 256;
					
					// 等待写入时间间隔
					Thread.Sleep(updateTimeSpan);

					if (withProcess)
					{
						updateProcessValue = i * 100 / packetNum;
						this.BeginInvoke(updateBatWriteProcessValueDelegate, updateProcessValue);
					}
				}

				if (length % 256 > 0)	// 末尾数据 - 目前数据已对齐, 无末尾数据
				{
					;
				}
			}

			/********************************* End 写入数据 ***************************************/

			if (withProcess)
			{
				updateProcessValue = 100;
				this.BeginInvoke(updateBatWriteProcessValueDelegate, updateProcessValue);
			}

			batWriteProcessing = false;
			this.BeginInvoke(printBatWriteLogDelegate, "Batch WriteSubMem Done");
			this.BeginInvoke(batWriteDoneDelegate);
		}

		// 批量读操作结束后处理
		private void batReadDone()
		{
			string msg = "批量读取完成";
			if (LanguageOper.available == true)
			{
				msg = LanguageOper.ReadValue(section, "msgStr.19");
			}

			MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);

			string text = "批量读取";
			if (LanguageOper.available == true)
			{
				text = LanguageOper.ReadValue(section, "batReadButton.Text.0");
			} 
		
			batReadButton.Text = text;
			
			enableComponentsAfterBatRead();
		}

		// 批量写操作结束后处理
		private void batWriteDone()
		{
			string msg = "批量写入完成";
			if (LanguageOper.available == true)
			{
				msg = LanguageOper.ReadValue(section, "msgStr.20");
			}

			MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);

			string text = "";
			if (LanguageOper.available == true)
			{
				text = LanguageOper.ReadValue(section, "batWriteButton.Text.0");
			}

			batWriteButton.Text = text;
			
			enableComponentsAfterBatWrite();
		}

		#endregion

		#region 界面控件响应

		private void UIForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (batWriteProcessing == true)
			{
				string msg = "批量写操作正在执行, 请先停止操作或等待操作结束";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.21");
				}

				MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
				
				e.Cancel = true;
				
				return;
			}
			else if (batReadProcessing == true)
			{
				string msg = "批量读操作正在执行, 请先停止操作或等待操作结束";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.22");
				}

				MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);

				e.Cancel = true;

				return;
			}
			else
			{
				exitFlag = true;
				this.Hide();
			}
		}

		private void printOnlineDetectResult(string str)
		{
			if (!str.EndsWith("\n"))
			{
				str += "\n";
			}

			detectResultTextBox.AppendText(str);
		}

		private void printReadResult(string str)
		{
			resultRichTextBox_read.Text = "";

			if (!str.EndsWith("\n"))
			{
				str += "\n";
			}

			resultRichTextBox_read.AppendText(str);
		}

		private void printBatReadResult(string str)
		{
			dataRichTextBox_batRead.Text = "";

			if (!str.EndsWith("\n"))
			{
				str += "\n";
			}

			dataRichTextBox_batRead.AppendText(str);
		}

		private void detectResultTextBox_TextChanged(object sender, EventArgs e)
		{
			detectResultTextBox.SelectionStart = detectResultTextBox.Text.Length;
			detectResultTextBox.ScrollToCaret();
		}

		private void printBatReadLog(string str)
		{
			if (!str.EndsWith("\n"))
			{
				str += "\n";
			}

			logRichTextBox_batRead.AppendText(str);
		}

		private void printBatWriteLog(string str)
		{
			if (!str.EndsWith("\n"))
			{
				str += "\n";
			}

			logRichTextBox_batWrite.AppendText(str);
		}

		private void logRichTextBox_batWrite_TextChanged(object sender, EventArgs e)
		{
			logRichTextBox_batWrite.SelectionStart = logRichTextBox_batWrite.Text.Length;
			logRichTextBox_batWrite.ScrollToCaret();
		}

		private void startDetectResultButton_Click(object sender, EventArgs e)
		{
			if (onlineTestRunning == false)
			{
				string text = "停止检测";
				if (LanguageOper.available == true)
				{
					text = LanguageOper.ReadValue(section, "startDetectResultButton.Text.0");
				}

				startDetectResultButton.Text = text;
				onlineTestRunning = true;
			}
			else if (onlineTestRunning == true)
			{
				string text = "开始检测";
				if (LanguageOper.available == true)
				{
					text = LanguageOper.ReadValue(section, "startDetectResultButton.Text.1");
				}

				startDetectResultButton.Text = text;
				
				this.onlineTestRunning = false;
			}
		}

		private void clearDetectButton_Click(object sender, EventArgs e)
		{
			detectResultTextBox.Text = "";
		}

		private void refreshButton_Click(object sender, EventArgs e)
		{
			refreshDeviceList();
		}

		private void subRadioButton_read_CheckedChanged(object sender, EventArgs e)
		{
			// 读操作对象为 分控, 深度范围 1 - 255
			if (subRadioButton_read.Checked)
			{
				indexComboBox_read.Items.Clear();
				for (int k = 1; k <= 255; k++)
				{
					indexComboBox_read.Items.Add(k);
				}
				indexComboBox_read.SelectedIndex = 0;
			}
			// 读操作对象为 附属设备, 深度范围 1 - 63
			else
			{
				indexComboBox_read.Items.Clear();
				for (int k = 1; k <= 63; k++)
				{
					indexComboBox_read.Items.Add(k);
				}
				indexComboBox_read.SelectedIndex = 0;
			}
		}

		private void subRadioButton_write_CheckedChanged(object sender, EventArgs e)
		{
			string all = "全局";
			if (LanguageOper.available == true)
			{
				all = LanguageOper.ReadValue(section, "str.0");
			}

			// 写操作对象为 分控, 深度范围 1 - 255
			if (subRadioButton_write.Checked)
			{
				indexComboBox_write.Items.Clear();
				indexComboBox_write.Items.Add(all);
				for (int k = 1; k <= 255; k++)
				{
					indexComboBox_write.Items.Add(k);
				}
				indexComboBox_write.SelectedIndex = 1;
			}
			// 写操作对象为 附属设备, 深度范围 1 - 63
			else
			{
				indexComboBox_write.Items.Clear();
				indexComboBox_write.Items.Add(all);
				for (int k = 1; k <= 63; k++)
				{
					indexComboBox_write.Items.Add(k);
				}
				indexComboBox_write.SelectedIndex = 1;
			}
		}

		private void readButton_Click(object sender, EventArgs e)
		{
			save2FileButton.Enabled = false;

			// 读 分控 操作
			if (subRadioButton_read.Checked)
			{
				readSubProcess();
			}
			// 读 附属设备 操作
			else
			{
				readEquProcess();
			}
		}

		private void clearReadResultButton_Click(object sender, EventArgs e)
		{
			resultRichTextBox_read.Text = "";
			save2FileButton.Enabled = false;
		}

		private void save2FileButton_Click(object sender, EventArgs e)
		{
			SaveFileDialog s = new SaveFileDialog();
			s.Filter = "Bin Files(*.bin)|*.bin";
			s.CheckFileExists = false;
			DialogResult opdr = s.ShowDialog();
			if (opdr == DialogResult.OK)
			{
				datFilePath = s.FileName;

				// 写入文件
				FileStream fs = new FileStream(datFilePath, FileMode.Create);
				BinaryWriter writer = new BinaryWriter(fs);
				
				writer.Write(memData_read);
				
				writer.Flush();
				writer.Close();
				fs.Close();

				string msg = "文件保存成功";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.23");
				}

				MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
		}

		private void setWaitTimeButton_Click(object sender, EventArgs e)
		{
			try
			{
				int wait_ms = Convert.ToInt32(waitTimeTextBox.Text);
				if (wait_ms > 0)
				{
					config_waitPacket_ms = wait_ms;

					baseCoreNet.setWaitTime_ms(config_waitPacket_ms);

					string msg = "回包等待间隔设置成功";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.24");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
				else
				{
					string msg = "回包等待间隔：请输入大于 0 的整数";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.25");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
			}
			catch (Exception ex)
			{
				MessageBoxEx.Show(this, ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void setGetResSpanButton_Click(object sender, EventArgs e)
		{
			try
			{
				int get_ms = Convert.ToInt32(getResultSpanTextBox.Text);
				if (get_ms > 0)
				{
					config_getResult_ms = get_ms;

					string msg = "获取结果周期设置成功";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.26");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
				else
				{
					string msg = "获取结果周期：请输入大于 0 的整数";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.27");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
			}
			catch (Exception ex)
			{
				MessageBoxEx.Show(this, ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void setNumButton_Click(object sender, EventArgs e)
		{
			try
			{
				int maxSubNum = Convert.ToInt32(maxSubNumTextBox.Text);
				int maxEquNum = Convert.ToInt32(maxEquNumTextBox.Text);
				if (maxSubNum < 1 || maxSubNum > 255)
				{
					string msg = "最大分控数量：请输入大于 1~255 之间的整数";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.28");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
					
					return;
				}
				if (maxEquNum < 1 || maxEquNum > 63)
				{
					string msg = "最大附属设备数量：请输入大于 1~63 之间的整数";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.29");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);

					return;
				}

				config_maxSubCtrlNum = maxSubNum;
				config_maxEquipmentNum = maxEquNum;

				baseCoreNet.setMaxSubEquNum(config_maxSubCtrlNum, config_maxEquipmentNum);

				string msg1 = "最大分控/附属设备数量设置成功";
				if (LanguageOper.available == true)
				{
					msg1 = LanguageOper.ReadValue(section, "msgStr.30");
				}

				MessageBoxEx.Show(this, msg1, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
			catch (Exception ex)
			{
				MessageBoxEx.Show(this, ex.Message, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
		}

		private void writeButton_Click(object sender, EventArgs e)
		{
			// 写 分控 操作
			if (subRadioButton_write.Checked)
			{
				writeSubProcess();
			}
			// 写 附属设备 操作
			else
			{
				writeEquProcess();
			}
		}

		private void selectDataFileButton_Click(object sender, EventArgs e)
		{
			OpenFileDialog o = new OpenFileDialog();
			o.Filter = "Bin Files(*.bin)|*.bin|Rbf Files(*.rbf)|*.rbf|Dat Files(*.dat)|*.dat";
			o.Multiselect = false;
			if (Directory.Exists(lastPath_DataFile))
			{
				o.InitialDirectory = lastPath_DataFile;
			}
			else
			{
				o.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
			}
			if (o.ShowDialog() == DialogResult.OK)
			{
				lastPath_DataFile = (new FileInfo(o.FileName)).DirectoryName;

				dataFilePathTextBox.Text = o.FileName;
				
				FileStream fs = File.OpenRead(o.FileName);
				BinaryReader reader = new BinaryReader(fs);
				memData_write = reader.ReadBytes(256);

				previewRichTextBox.Text = Tools.Byte2HexString4RBF(memData_write);
				writeButton.Enabled = true;

				commonValueComboBox.SelectedIndex = 0;
			}
		}

		private void clearWritePreviewButton_Click(object sender, EventArgs e)
		{
			previewRichTextBox.Text = "";
			writeButton.Enabled = false;
			dataFilePathTextBox.Text = "";
			commonValueComboBox.SelectedIndex = 0;
		}

		private void commonValueComboBox_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (commonValueComboBox.SelectedIndex == 0)
			{
				;
			}
			// 典型值0x00
			else if (commonValueComboBox.SelectedIndex == 1)
			{
				for (int i = 0; i < 256; i++)
				{
					memData_write[i] = 0x00;
				}

				dataFilePathTextBox.Text = "";
				previewRichTextBox.Text = Tools.Byte2HexString4RBF(memData_write);
				writeButton.Enabled = true;
			}
			// 典型值0xFF
			else if (commonValueComboBox.SelectedIndex == 2)
			{
				for (int i = 0; i < 256; i++)
				{
					memData_write[i] = 0xFF;
				}

				dataFilePathTextBox.Text = "";
				previewRichTextBox.Text = Tools.Byte2HexString4RBF(memData_write);
				writeButton.Enabled = true;
			}
		}

		private void depthRadioButton2_CheckedChanged(object sender, EventArgs e)
		{
			if (depthRadioButton2.Checked)
			{
				baseCoreNet.setDepthReadPosition(DepthReadPos.Pos_59_61);
			}
			else
			{
				baseCoreNet.setDepthReadPosition(DepthReadPos.Pos_54_56);
			}
		}

		private void subRadioButton_batRead_CheckedChanged(object sender, EventArgs e)
		{
			// 写操作对象为 分控, 深度范围 1 - 255
			if (subRadioButton_batRead.Checked)
			{
				indexComboBox_batRead.Items.Clear();
				for (int k = 1; k <= 255; k++)
				{
					indexComboBox_batRead.Items.Add(k);
				}
				indexComboBox_batRead.SelectedIndex = 0;
			}
			// 写操作对象为 附属设备, 深度范围 1 - 63
			else
			{
				indexComboBox_batRead.Items.Clear();
				for (int k = 1; k <= 63; k++)
				{
					indexComboBox_batRead.Items.Add(k);
				}
				indexComboBox_batRead.SelectedIndex = 0;
			}
		}

		private void subRadioButton_batWrite_CheckedChanged(object sender, EventArgs e)
		{
			string all = "全局";
			if (LanguageOper.available == true)
			{
				all = LanguageOper.ReadValue(section, "str.0");
			}

			// 写操作对象为 分控, 深度范围 1 - 255
			if (subRadioButton_batWrite.Checked)
			{
				indexComboBox_batWrite.Items.Clear();
				indexComboBox_batWrite.Items.Add(all);
				for (int k = 1; k <= 255; k++)
				{
					indexComboBox_batWrite.Items.Add(k);
				}
				indexComboBox_batWrite.SelectedIndex = 1;
			}
			// 写操作对象为 附属设备, 深度范围 1 - 63
			else
			{
				indexComboBox_batWrite.Items.Clear();
				indexComboBox_batWrite.Items.Add(all);
				for (int k = 1; k <= 63; k++)
				{
					indexComboBox_batWrite.Items.Add(k);
				}
				indexComboBox_batWrite.SelectedIndex = 1;
			}
		}

		private void selectBatDataFileButton_Click(object sender, EventArgs e)
		{
			OpenFileDialog o = new OpenFileDialog();
			o.Filter = "Bin Files(*.bin)|*.bin|Rbf Files(*.rbf)|*.rbf|Dat Files(*.dat)|*.dat";
			o.Multiselect = false;
			if (Directory.Exists(lastPath_BatDataFile))
			{
				o.InitialDirectory = lastPath_BatDataFile;
			}
			else
			{
				o.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
			}
			if (o.ShowDialog() == DialogResult.OK)
			{
				lastPath_BatDataFile = (new FileInfo(o.FileName)).DirectoryName;

				dataFilePathTextBox_batWrite.Text = o.FileName;

				FileStream fs = File.OpenRead(o.FileName);
				BinaryReader reader = new BinaryReader(fs);
				memData_batWrite = new byte[fs.Length];
				memData_batWrite = reader.ReadBytes((int)fs.Length);

				dataRichTextBox_batWrite.Text = Tools.Byte2HexString4RBF(memData_batWrite);
				batWriteButton.Enabled = true;

				logRichTextBox_batWrite.Text = "";
				totalLengthLabel_batWrite.Text = String.Format("{0:#.##} KB", (double)(fs.Length) / 1024.0);
			}
		}

		private void clearBatWritePreviewButton_Click(object sender, EventArgs e)
		{
			dataRichTextBox_batWrite.Text = "";
			batWriteButton.Enabled = false;
			dataFilePathTextBox_batWrite.Text = "";
			memData_batWrite = null;
			logRichTextBox_batWrite.Text = "";
			totalLengthLabel_batWrite.Text = "0 KB";
			startAddrType_batWrite.Text = "--";
			progressBar_batWrite.Value = 0;
			processLabel_batWrite.Text = "0 %";
		}

		private void clearLogButton_batRead_Click(object sender, EventArgs e)
		{
			logRichTextBox_batRead.Text = "";
		}

		private void clearLogButton_batWrite_Click(object sender, EventArgs e)
		{
			logRichTextBox_batWrite.Text = "";
		}

		private void batReadButton_Click(object sender, EventArgs e)
		{
			string rulerStr = "强制停止";
			if (LanguageOper.available == true)
			{
				rulerStr = LanguageOper.ReadValue(section, "batReadButton.Text.1");
			}

			if (batReadButton.Text.Equals(rulerStr))
			{
				string msg = "确认强制停止批量读操作？";
				string text = "批量读取";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.31");
					text = LanguageOper.ReadValue(section, "batReadButton.Text.0");
				}

				DialogResult dr = MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
				
				if (dr == DialogResult.OK)
				{
					forceStopBatRead = true;
					batReadButton.Text = text;
				}
				else
				{
					return;
				}
			}
			else
			{
				// 执行刷新操作, 自动选择网卡
				refreshDeviceList();

				// 批量写 分控/附属设备 操作入口
				batReadEntry();
			}
		}

		private void batWriteButton_Click(object sender, EventArgs e)
		{
			string rulerStr = "强制停止";
			if (LanguageOper.available == true)
			{
				rulerStr = LanguageOper.ReadValue(section, "batWriteButton.Text.1");
			}

			if (batWriteButton.Text.Equals(rulerStr))
			{
				string msg = "确认强制停止批量写操作？";
				string text = "批量写入";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.32");
					text = LanguageOper.ReadValue(section, "batWriteButton.Text.0");
				}

				DialogResult dr = MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
				
				if (dr == DialogResult.OK)
				{
					forceStopBatWrite = true;
					batWriteButton.Text = text;
				}
				else
				{
					return;
				}
			}
			else
			{
				// 执行刷新操作, 自动选择网卡
				refreshDeviceList();

				// 批量写 分控/附属设备 操作入口
				batWriteEntry();
			}
		}

		private void updateBatReadProcessValue(int value)
		{
			if (value >= 0 && value <= 100)
			{
				progressBar_batRead.Value = value;
				processLabel_batRead.Text = value + " %";
			}
		}

		private void updateBatWriteProcessValue(int value)
		{
			if (value >= 0 && value <= 100)
			{
				progressBar_batWrite.Value = value;
				processLabel_batWrite.Text = value + " %";
			}
		}

		private void disableComponentsBeforeBatRead()
		{
			// 批量读时, 禁用界面控件
			subRadioButton_batRead.Enabled = false;
			equRadioButton_batRead.Enabled = false;
			indexComboBox_batRead.Enabled = false;
			selectDataFileButton_batRead.Enabled = false;
			clearResultButton_batRead.Enabled = false;
			selectDataFileButton_batRead.Enabled = false;
			saveLogButton_batRead.Enabled = false;
			clearLogButton_batRead.Enabled = false;
		}

		private void enableComponentsAfterBatRead()
		{
			// 批量读后, 启用界面控件
			subRadioButton_batRead.Enabled = true;
			equRadioButton_batRead.Enabled = true;
			indexComboBox_batRead.Enabled = true;
			selectDataFileButton_batRead.Enabled = true;
			clearResultButton_batRead.Enabled = true;
			selectDataFileButton_batRead.Enabled = true;
			saveLogButton_batRead.Enabled = true;
			clearLogButton_batRead.Enabled = true;
		}

		private void disableComponentsBeforeBatWrite()
		{
			// 批量写时, 禁用界面控件
			subRadioButton_batWrite.Enabled = false;
			equRadioButton_batWrite.Enabled = false;
			indexComboBox_batWrite.Enabled = false;
			selectDataFileButton_batWrite.Enabled = false;
			clearWritePreviewButton_batWrite.Enabled = false;
			fileBatDataRadioButton.Enabled = false;
			saveLogButton_batWrite.Enabled = false;
			clearLogButton_batWrite.Enabled = false;
		}

		private void enableComponentsAfterBatWrite()
		{
			// 批量写后, 启用界面控件
			subRadioButton_batWrite.Enabled = true;
			equRadioButton_batWrite.Enabled = true;
			indexComboBox_batWrite.Enabled = true;
			selectDataFileButton_batWrite.Enabled = true;
			clearWritePreviewButton_batWrite.Enabled = true;
			fileBatDataRadioButton.Enabled = true;
			saveLogButton_batWrite.Enabled = true;
			clearLogButton_batWrite.Enabled = true;
		}

		private void saveBatWriteLogButton_Click(object sender, EventArgs e)
		{
			string batWriteLogFilePath = "";
			SaveFileDialog s = new SaveFileDialog();
			s.Filter = "Log Files(*.log)|*.log";
			s.CheckFileExists = false;
			s.FileName = "batWriteLog.log";
			DialogResult opdr = s.ShowDialog();
			if (opdr == DialogResult.OK)
			{
				batWriteLogFilePath = s.FileName;

				// 写入文件
				FileStream fs = new FileStream(batWriteLogFilePath, FileMode.Create);
				StreamWriter writer = new StreamWriter(fs);

				writer.Write(logRichTextBox_batWrite.Text);

				writer.Flush();
				writer.Close();
				fs.Close();

				string msg = "日志保存成功";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.33");
				}
				
				MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
		}

		private void clearResultButton_batRead_Click(object sender, EventArgs e)
		{
			dataRichTextBox_batRead.Text = "";

			dataFilePathTextBox_batRead.Text = "";

			memData_batRead = null;

			this.BeginInvoke(updateBatReadProcessValueDelegate, 0);
		}

		private void selectDataFileButton_batRead_Click(object sender, EventArgs e)
		{
			if (memData_batRead != null)
			{
				SaveFileDialog s = new SaveFileDialog();
				s.Filter = "Bin Files(*.bin)|*.bin";
				s.FileName = "batReadData.bin";
				s.CheckFileExists = false;
				DialogResult opdr = s.ShowDialog();
				if (opdr == DialogResult.OK)
				{
					batReadBinFilePath = s.FileName;
					
					dataFilePathTextBox_batRead.Text = batReadBinFilePath;

					// 写入文件
					FileStream fs = new FileStream(batReadBinFilePath, FileMode.Create);
					BinaryWriter writer = new BinaryWriter(fs);

					writer.Write(memData_batRead);

					writer.Flush();
					writer.Close();
					fs.Close();

					string msg = "文件保存成功";
					if (LanguageOper.available == true)
					{
						msg = LanguageOper.ReadValue(section, "msgStr.23");
					}

					MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
			}
		}

		private void saveLogButton_batRead_Click(object sender, EventArgs e)
		{
			string batReadLogFilePath = "";
			SaveFileDialog s = new SaveFileDialog();
			s.Filter = "Log Files(*.log)|*.log";
			s.CheckFileExists = false;
			s.FileName = "batReadLog.log";
			DialogResult opdr = s.ShowDialog();
			if (opdr == DialogResult.OK)
			{
				batReadLogFilePath = s.FileName;

				// 写入文件
				FileStream fs = new FileStream(batReadLogFilePath, FileMode.Create);
				StreamWriter writer = new StreamWriter(fs);

				writer.Write(logRichTextBox_batRead.Text);

				writer.Flush();
				writer.Close();
				fs.Close();

				string msg = "日志保存成功";
				if (LanguageOper.available == true)
				{
					msg = LanguageOper.ReadValue(section, "msgStr.33");
				}

				MessageBoxEx.Show(this, msg, tip, MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
		}

		#endregion
	}
}
